package com.youlu.campus.service.order;

import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.QaOrderReq;
import com.youlu.campus.entity.commission.DistributorApply;
import com.youlu.campus.entity.commission.dto.DistributorChannelSharingCommissionOrderDTO;
import com.youlu.campus.entity.commission.dto.SharingCommissionOrderDTO;
import com.youlu.campus.entity.course.ActivityCourse;
import com.youlu.campus.entity.course.UserCourseOrder;
import com.youlu.campus.entity.course.dto.CourseInfoDTO;
import com.youlu.campus.entity.course.vo.CourseOrderVo;
import com.youlu.campus.entity.enums.CourseOrderStatusEnum;
import com.youlu.campus.entity.enums.CourseOrderTypeEnum;
import com.youlu.campus.entity.enums.SharingProfitOrderTypeEnum;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.UserParticipateActivityInfoService;
import com.youlu.campus.service.base.LockService;
import com.youlu.campus.service.commission.ContestQaOrderCommissionServiceService;
import com.youlu.campus.service.commission.DistributorChannelSharingCommissionService;
import com.youlu.campus.service.course.UserCourseOrderService;
import com.youlu.campus.service.qa.ActivityQaInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 竞赛答题订单服务类
 */
@Slf4j
@Service
public class ContestQaOrderService {

    @Autowired
    private ActivityService activityService;

    @Autowired
    private ActivityQaInfoService activityQaInfoService;

    @Autowired
    private UserCourseOrderService userCourseOrderService;


    @Autowired
    private LockService lockService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private MerchantSharingProfitService merchantSharingProfitService;

    @Autowired
    private ContestQaOrderCommissionServiceService contestQaOrderCommissionServiceService;

    @Autowired
    private DistributorChannelSharingCommissionService distributorChannelSharingCommissionService;

    @Lazy
    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;

    /**
     * 处理订单支付通知
     *
     * @param orderNo       订单号
     * @param transactionId 交易号
     */
    public void handlePayNotifyOrder(String orderNo, String transactionId) {
        log.info("【支付回调通知】orderNo:{}|transactionId:{}", orderNo, transactionId);
        UserCourseOrder order = userCourseOrderService.getOrderByOrderNo(orderNo);
        log.info("ContestQaOrderService,handlePayNotifyOrder,before deal order orderNo:{} orderStatus:{}", orderNo,
                order.getStatus());
        if (order == null) {
            log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} not exist", orderNo);
            return;
        }
        CourseOrderStatusEnum statusEnum = CourseOrderStatusEnum.getByType(order.getStatus());
        switch (statusEnum) {
            case PAY_SUCCESS:
                log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} has pay success", orderNo);
                return;
            case REFUND_APPLY:
                log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} refund apply", orderNo);
                return;
            case REFUND_COMPLETE:
                log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} has refund success", orderNo);
                return;
            case PAY_FIAL:
                log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} pay fail", orderNo);
                return;
            case NOT_PAY:
                // 失效如果支付成功了，也处理
            case EXPIRED:
                // 更新订单状态
                order.setStatus(CourseOrderStatusEnum.PAY_SUCCESS.getValue());
                order.setPayTime(LocalDateTime.now());
                order.setTransactionId(transactionId);
                mongoTemplate.save(order);
                Integer courseOrderType = order.getCourseOrderType();
                String sharingProfitOrderType = SharingProfitOrderTypeEnum.CHU_SAI_ORDER.name();
                switch (courseOrderType) {
                    case 2:
                        sharingProfitOrderType = SharingProfitOrderTypeEnum.CHU_SAI_ORDER.name();
                        break;
                    case 3:
                        sharingProfitOrderType = SharingProfitOrderTypeEnum.FU_SAI_ORDER.name();
                        break;
                    case 4:
                        sharingProfitOrderType = SharingProfitOrderTypeEnum.JUE_SAI_ORDER.name();
                        break;
                }
                Integer sharingCommissionOrderAmount = 0;
                Integer sharingCommissionChannelOrderAmount = 0;
                //总订单金额减去分拥订单后金额
                Integer orderAmountAfter = 0;
                //分拥-个人
                UserInviteRecord userInviteRecord =
                        contestQaOrderCommissionServiceService.inviterDistributor(order.getUserId(),
                                order.getActivityId());
                if (Objects.nonNull(userInviteRecord) && userInviteRecord.getInviterDistributor()) {
                    DistributorApply distributorApply =
                            contestQaOrderCommissionServiceService.findByDistributorId(userInviteRecord.getInvitedByUserId());
                    if (Objects.nonNull(distributorApply)) {
                        SharingCommissionOrderDTO sharingCommissionOrderDto = new SharingCommissionOrderDTO();
                        sharingCommissionOrderDto.setBusinessType(courseOrderType);
                        sharingCommissionOrderDto.setActivityId(order.getActivityId());
                        sharingCommissionOrderDto.setDistributorCommission(distributorApply.getDistributorCommission());
                        sharingCommissionOrderDto.setMerchantId(order.getMerchantId());
                        sharingCommissionOrderDto.setAppId(order.getAppId());
                        sharingCommissionOrderDto.setMerchantName(order.getMerchantName());
                        sharingCommissionOrderDto.setOrderNo(orderNo);
                        sharingCommissionOrderDto.setPayTime(Date.from(order.getPayTime().atZone(ZoneId.systemDefault()).toInstant()));
                        sharingCommissionOrderDto.setTotalFee(order.getPrice());
                        sharingCommissionOrderDto.setTransactionId(order.getTransactionId());
                        sharingCommissionOrderDto.setCategory(sharingProfitOrderType);
                        sharingCommissionOrderAmount = contestQaOrderCommissionServiceService.doSharingCommissionAmount(sharingCommissionOrderDto);
                    }
                } else {
                    //渠道分拥
                    String activityChannelId = order.getActivityChannelId();
                    DistributorChannelSharingCommissionOrderDTO sharingCommissionOrderChannelDto = new DistributorChannelSharingCommissionOrderDTO();
                    sharingCommissionOrderChannelDto.setActivityId(order.getActivityId());
                    sharingCommissionOrderChannelDto.setAppId(order.getAppId());
                    sharingCommissionOrderChannelDto.setOrderNo(orderNo);
                    sharingCommissionOrderChannelDto.setMerchantId(order.getMerchantId());
                    sharingCommissionOrderChannelDto.setMerchantName(order.getMerchantName());
                    sharingCommissionOrderChannelDto.setActivityChannelId(activityChannelId);
                    sharingCommissionOrderChannelDto.setPayTime(Date.from(order.getPayTime().atZone(ZoneId.systemDefault()).toInstant()));
                    sharingCommissionOrderChannelDto.setTotalFee(order.getPrice());
                    sharingCommissionOrderChannelDto.setTransactionId(transactionId);
                    sharingCommissionOrderChannelDto.setCategory(sharingProfitOrderType);
                    sharingCommissionOrderChannelDto.setUserId(order.getUserId());
                    sharingCommissionOrderChannelDto.setMobile(order.getPhone());
                    sharingCommissionOrderChannelDto.setName(order.getName());
                    UserParticipateActivityInfo user = userParticipateActivityInfoService.findByUserIdActivityId(order.getUserId(), order.getActivityId());
                    if (Objects.nonNull(user)) {
                        sharingCommissionOrderChannelDto.setUniversityId(user.getUniversityId());
                        sharingCommissionOrderChannelDto.setUniversityName(user.getUniversityName());
                    }

                    sharingCommissionChannelOrderAmount = distributorChannelSharingCommissionService.doSharingCommissionAmount(sharingCommissionOrderChannelDto);
                }
                if (sharingCommissionOrderAmount > 0 || sharingCommissionChannelOrderAmount > 0) {
                    orderAmountAfter = order.getPrice() - Math.addExact(sharingCommissionOrderAmount, sharingCommissionChannelOrderAmount);
                } else {
                    orderAmountAfter = order.getPrice();
                }
                OrderInfo sharingProfitOrder = new OrderInfo();
                sharingProfitOrder.setOrderNo(orderNo);
                sharingProfitOrder.setActivityId(order.getActivityId());
                sharingProfitOrder.setCategory(sharingProfitOrderType);
                sharingProfitOrder.setTotalFee(orderAmountAfter);
                sharingProfitOrder.setPayTime(Date.from(order.getPayTime().atZone(ZoneId.systemDefault()).toInstant()));
                sharingProfitOrder.setTransactionId(transactionId);
                sharingProfitOrder.setAppId(order.getAppId());
                sharingProfitOrder.setMechantId(order.getMerchantId());
                sharingProfitOrder.setMechantName(order.getMerchantName());
                merchantSharingProfitService.doSharingProfit(sharingProfitOrder);
                log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} pay success", orderNo);
                return;
        }

    }

    /**
     * 处理H5支付订单支付通知
     *
     * @param orderNo       订单号
     * @param transactionId 交易号
     */
    @Async
    public void handleH5OrderPayNotifyOrder(String orderNo, String transactionId) {
        log.info("【支付回调通知】orderNo:{}|transactionId:{}", orderNo, transactionId);
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo));
        OrderInfo order = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(order)) {
            log.error(":>>> 订单不存在:{}", orderNo);
            return;
        }
        Integer sharingCommissionOrderAmount = 0;
        Integer sharingCommissionChannelOrderAmount = 0;
        //总订单金额减去分拥订单后金额
        Integer orderAmountAfter = 0;

        if (sharingCommissionOrderAmount > 0 || sharingCommissionChannelOrderAmount > 0) {
            orderAmountAfter = order.getTotalFee() - Math.addExact(sharingCommissionOrderAmount, sharingCommissionChannelOrderAmount);
        } else {
            orderAmountAfter = order.getTotalFee();
        }
        OrderInfo sharingProfitOrder = new OrderInfo();
        sharingProfitOrder.setOrderNo(orderNo);
        sharingProfitOrder.setActivityId(order.getActivityId());
        sharingProfitOrder.setCategory(SharingProfitOrderTypeEnum.H5_ORDER.name());
        sharingProfitOrder.setTotalFee(orderAmountAfter);
        sharingProfitOrder.setPayTime(order.getPayTime());
        sharingProfitOrder.setTransactionId(transactionId);
        sharingProfitOrder.setAppId(order.getAppId());
        sharingProfitOrder.setMechantId(order.getMechantId());
        sharingProfitOrder.setMechantName(order.getMechantId());
        merchantSharingProfitService.doSharingProfit(sharingProfitOrder);
        log.warn("ContestQaOrderService,handlePayNotifyOrder,orderNo:{} pay success", orderNo);
        return;

    }

    public Object createOrder(QaOrderReq qaOrderReq) {
        String activityId = qaOrderReq.getActivityId();
        UserPO currentUser = qaOrderReq.getCurrentUser();
        String qaInfoId = qaOrderReq.getQaInfoId();
        log.info("【竞赛答题订单】createOrder userId:{}|qaInfoId:{}|activityId:{}", currentUser.getId(), qaInfoId, activityId);
        ActivityInfo activityInfo = activityService.findOne(activityId);
        if (Objects.isNull(activityInfo)) {
            log.error("【竞赛答题订单】createOrder userId:{}|qaInfoId:{}|activityId:{} 活动不存在", currentUser.getId(), qaInfoId,
                    activityId);
            throw new BusinessException("服务繁忙");
        }
        ActivityQaInfo activityQaInfo = activityQaInfoService.findOne(qaInfoId);
        if (Objects.isNull(activityQaInfo)) {
            log.error("【竞赛答题订单】createOrder userId:{}|qaInfoId:{}|activityId:{} 题库不存在", currentUser.getId(), qaInfoId,
                    activityId);
            throw new BusinessException("题库不存在");
        }
        String key = "course.video.create.order.userId:%s";
        key = String.format(key, qaInfoId);
        log.info("ContestQaOrderService,userId:{} key:{} createOrder add lock", currentUser.getId(), key);
        if (!lockService.tryLock(key, 1, TimeUnit.MINUTES)) {
            throw new BusinessException("请不要重复操作");
        }
        Integer qaNumber = activityQaInfo.getNo();
        Integer payFee = 0;
        Integer courseOrderType = CourseOrderTypeEnum.CHU_SAI.getValue();
        switch (qaNumber) {
            case 1:
                payFee = activityInfo.getChuSaiFee();
                courseOrderType = CourseOrderTypeEnum.CHU_SAI.getValue();
                break;
            case 2:
                payFee = activityInfo.getFuSaiFee();
                courseOrderType = CourseOrderTypeEnum.FU_SAI.getValue();
                break;
            case 3:
                payFee = activityInfo.getJueSaiFee();
                courseOrderType = CourseOrderTypeEnum.JUE_SAI.getValue();
                break;
            default:
        }
        log.info("【竞赛答题订单】createOrder userId:{}|qaInfoId:{}|activityId:{}|qaNumber:{}|payFee:{}", currentUser.getId(),
                qaInfoId,
                activityId, qaNumber, payFee);
        if (payFee == 0) {
            log.error("【竞赛答题订单】createOrder userId:{}|qaInfoId:{}|activityId:{} 金额为不能为0", currentUser.getId(), qaInfoId,
                    activityId);
            throw new BusinessException("服务繁忙");
        }
        Triple<Boolean, Object, String> result = null;
        try {
            CourseInfoDTO dto = new CourseInfoDTO();
            dto.setCourseOrderType(courseOrderType);
            dto.setCourseId(qaInfoId);
            dto.setQaInfoId(qaInfoId);
            dto.setAppId(qaOrderReq.getAppId());
            dto.setUserPO(qaOrderReq.getCurrentUser());
            dto.setUserId(qaOrderReq.getCurrentUser().getId());
            dto.setPlatform(qaOrderReq.getPlatform());
            dto.setActivityId(activityId);
            dto.setClientIp(qaOrderReq.getClientIp());
            dto.setNotifyUrl(qaOrderReq.getNotifyUrl());
            ActivityCourse activityCourse = new ActivityCourse();
            activityCourse.setPrice(payFee);
            activityCourse.setName(activityQaInfo.getName());
            result = userCourseOrderService.getPayInfo(dto, activityCourse);
            if (result.getLeft()) {
                return new CourseOrderVo(1, result.getMiddle());
            }
        } catch (Exception e) {
            log.error("ContestQaOrderService,userId:{}, key:{} createOrder error", currentUser.getId(), key, e);
        } finally {
            log.info("ContestQaOrderService,userId:{}, key:{} createOrder unlock success", currentUser.getId(), key);
            lockService.unLock(key);
        }
        throw new BusinessException(result != null ? result.getRight() : "创建订单异常");
    }
}
